import re
import time
import json
from flask import request
from flask_restful import abort
from flask_login import current_user, login_user
from funcy import project
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.exc import IntegrityError
from funcy import partial

from redash import models, limiter
from redash.permissions import (
    require_permission,
    require_admin_or_owner,
    is_admin_or_owner,
    require_permission_or_owner,
    require_admin_default,
)
from redash.handlers.base import (
    BaseResource,
    require_fields,
    get_object_or_404,
    paginate,
    order_results as _order_results,
)

from redash.authentication.account import (
    invite_link_for_user,
    send_invite_email,
    send_password_reset_email,
    send_verify_email,
)
from redash.settings import parse_boolean
from redash import settings


class OrgUnitListResource(BaseResource):
    def get(self):
        page = request.args.get("page", 1, type=int)
        page_size = request.args.get("page_size", 100, type=int)

        def serialize_orgunit(orgunit):
            d = orgunit.to_dict()

            items = models.Enums.get_by_code("orgunit_enum",self.current_org).items
            names = []
            for code in set(d["orgunit_enums"]):
                one = list(filter(lambda item: item['value'] == code, items))

                if one:
                    names.append(one[0]["label"])

            d["orgunit_enums"] = names

            return d

        orgunit_enum = request.args.get("orgunit_enum", '')
        is_active = request.args.get("active", False, type=bool)

        #if orgunit_enum:
        #    results = models.OrgUnit.by_orgunit_enum(self.current_org, orgunit_enum)
        #else:
        results = models.OrgUnit.all(self.current_org)

        if orgunit_enum=="activate":
            results = results.filter(models.OrgUnit.is_active == True)
        elif orgunit_enum=="noactivate":
            results = results.filter(models.OrgUnit.is_active == False)
        results = results.order_by(models.OrgUnit.code.asc())

        return paginate(results, page, page_size, serialize_orgunit)

    @require_admin_default
    def post(self):
        req = request.get_json(force=True)
        require_fields(req, ("code", "name"))

        orgunit = models.OrgUnit(
            org=self.current_org,
            code=req["code"],
            name=req["name"],
            shortname=req["shortname"],
            orgunit_enums=[o for o in req["orgunit_enums"]],
            is_active=True,
        )

        try:
            models.db.session.add(orgunit)
            models.db.session.commit()
        except IntegrityError as e:
            if "code" in str(e):
                abort(400, message="编码已存在.")
            abort(500)

        self.record_event(
            {"action": "create", "object_id": orgunit.id, "object_type": "orgunit"}
        )


class OrgUnitListActiveResource(BaseResource):
    def get(self):
        results = models.OrgUnit.all(self.current_org).filter(models.OrgUnit.is_active == True).order_by(models.OrgUnit.name.asc())

        return [r.to_dict() for r in results]


class OrgUnitResource(BaseResource):
    def get(self, orgunit_id):
        result = models.OrgUnit.get_by_id_and_org(orgunit_id, self.current_org)
        return result.to_dict()

    @require_admin_default
    def post(self, orgunit_id):
        req = request.get_json(force=True)
        require_fields(req, ("code", "name"))

        orgunit = models.OrgUnit.get_by_id_and_org(orgunit_id, self.current_org)
        params = dict(code=req["code"], name=req["name"], orgunit_enums=req["orgunit_enums"],shortname=req["shortname"])

        try:
            self.update_model(orgunit, params)
            models.db.session.commit()
        except IntegrityError as e:
            if "code" in str(e):
                abort(400, message="编码已存在.")
            abort(500)

class OrgUnitdeleteResource(BaseResource):
    @require_admin_default
    def post(self, orgunit_id):
        orgunit = models.OrgUnit.get_by_id(orgunit_id)
        if orgunit.is_used():
            abort(400, message="部门已使用，不能删除！")
            return

        models.db.session.delete(orgunit)
        models.db.session.commit()


class OrgUnitActiveResource(BaseResource):
    @require_admin_default
    def get(self, orgunit_id):
        orgunit = models.OrgUnit.get_by_id_and_org(orgunit_id, self.current_org)
        params = dict(is_active=not orgunit.is_active)

        try:
            self.update_model(orgunit, params)
            models.db.session.commit()
        except IntegrityError as e:
            if "code" in str(e):
                abort(400, message="编码已存在.")
            abort(500)


class OrgUnitSelectResource(BaseResource):
    @require_admin_default
    def post(self, orgstruct_id):
        orgstruct = models.OrgStruct.get_by_id(orgstruct_id)

        if orgstruct.is_used():
            abort(400, message="部门已使用，不能再添加部门。")

        req = request.get_json(force=True)

        rs = ""
        for orgunit_id in req:
            if not orgstruct.has_orgunit(orgunit_id):
                orgunit = models.OrgUnit.get_by_id(orgunit_id)
                title =  orgunit.name #orgunit.shortname + ' ' +
                if len(rs) !=0:
                    rs=rs+ ","
                rs = rs+ "\'" + json.dumps(dict(key=str(orgunit_id), title=title)) + "\'::json"

        if len(rs) == 0:
            return

        sql = "update public.orgstruct set details = "
        if orgstruct.details is not None and len(orgstruct.details) != 0:
            sql = sql + "details || " 

        sql = sql + "ARRAY[" + rs  + "] where id=" + str(orgstruct_id)

        try:
            models.db.session.execute(sql)
            models.db.session.commit()
        except IntegrityError as e:
            if "code" in str(e):
                abort(400, message="编码已存在.")
            abort(500)

class OrgUnitListnewResource(BaseResource):
    def post(self):
        req = request.get_json(force=True)
        page = req["page"] if "page" in req else 1
        page_size = req["pagesize"] if "page_size" in req else 100
        orgunit_enum = req["orgunit_enum"] if "orgunit_enum" in req else '' # request.args.get("orgunit_enum", '')

        def serialize_orgunit(orgunit):
            d = orgunit.to_dict()

            items = models.Enums.get_by_code("orgunit_enum",self.current_org).items
            names = []
            for code in set(d["orgunit_enums"]):
                one = list(filter(lambda item: item['value'] == code, items))

                if one:
                    names.append(one[0]["label"])

            d["orgunit_enums"] = names

            return d

        is_active = request.args.get("active", False, type=bool)

        #if orgunit_enum:
        #    results = models.OrgUnit.by_orgunit_enum(self.current_org, orgunit_enum)
        #else:
        results = models.OrgUnit.all(self.current_org)

        if orgunit_enum=="activate":
            results = results.filter(models.OrgUnit.is_active == True)
        elif orgunit_enum=="noactivate":
            results = results.filter(models.OrgUnit.is_active == False)
        results = results.order_by(models.OrgUnit.code.asc())

        return paginate(results, page, page_size, serialize_orgunit)